package com.kaizeli.website.controller;

import com.kaizeli.website.response.Result;
import com.kaizeli.website.util.CaptchaUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 验证码控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/captcha")
@Tag(name = "验证码管理", description = "验证码生成和验证接口")
public class CaptchaController {

    private static final String CAPTCHA_SESSION_KEY = "CAPTCHA_CODE_";
    private static final long CAPTCHA_EXPIRE_TIME = 5 * 60 * 1000; // 5分钟过期

    // 使用Map存储验证码（生产环境建议使用Redis）
    private static final Map<String, CaptchaData> CAPTCHA_STORE = new HashMap<>();

    /**
     * 生成验证码
     */
    @GetMapping("/generate")
    @Operation(summary = "生成验证码", description = "生成4位数字图片验证码")
    public Result<Map<String, String>> generateCaptcha(HttpSession session) {
        try {
            // 生成验证码
            CaptchaUtil.CaptchaResult captcha = CaptchaUtil.generateCaptcha();
            
            // 生成唯一标识
            String captchaId = UUID.randomUUID().toString();
            
            // 存储验证码（存储到内存，生产环境建议使用Redis）
            CAPTCHA_STORE.put(captchaId, new CaptchaData(
                captcha.getCode(),
                System.currentTimeMillis()
            ));
            
            // 也存储到Session（备用方案）
            session.setAttribute(CAPTCHA_SESSION_KEY + captchaId, captcha.getCode());
            
            // 清理过期验证码
            cleanExpiredCaptcha();
            
            log.info("生成验证码成功，captchaId: {}", captchaId);
            
            Map<String, String> result = new HashMap<>();
            result.put("captchaId", captchaId);
            result.put("captchaImage", captcha.getImage());
            
            return Result.success(result);
            
        } catch (Exception e) {
            log.error("生成验证码失败：{}", e.getMessage(), e);
            return Result.error(500, "生成验证码失败");
        }
    }

    /**
     * 验证验证码（独立接口，可选）
     */
    @PostMapping("/verify")
    @Operation(summary = "验证验证码", description = "验证用户输入的验证码是否正确")
    public Result<Map<String, Object>> verifyCaptcha(
            @RequestParam String captchaId,
            @RequestParam String captchaCode,
            HttpSession session) {
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean isValid = validateCaptcha(captchaId, captchaCode, session);
            
            result.put("valid", isValid);
            result.put("message", isValid ? "验证码正确" : "验证码错误或已过期");
            
            return Result.success(result);
            
        } catch (Exception e) {
            log.error("验证验证码失败：{}", e.getMessage(), e);
            result.put("valid", false);
            result.put("message", "验证失败");
            return Result.error(500, "验证失败");
        }
    }

    /**
     * 验证验证码（内部方法）
     */
    public static boolean validateCaptcha(String captchaId, String captchaCode, HttpSession session) {
        if (captchaId == null || captchaCode == null) {
            return false;
        }
        
        // 从内存中获取验证码
        CaptchaData data = CAPTCHA_STORE.get(captchaId);
        
        if (data == null) {
            // 如果内存中没有，尝试从Session获取
            String sessionCode = (String) session.getAttribute(CAPTCHA_SESSION_KEY + captchaId);
            if (sessionCode == null) {
                log.warn("验证码不存在或已过期，captchaId: {}", captchaId);
                return false;
            }
            // 验证码不区分大小写
            boolean isValid = sessionCode.equalsIgnoreCase(captchaCode);
            // 验证后立即删除（一次性使用）
            session.removeAttribute(CAPTCHA_SESSION_KEY + captchaId);
            return isValid;
        }
        
        // 检查是否过期
        if (System.currentTimeMillis() - data.getCreateTime() > CAPTCHA_EXPIRE_TIME) {
            CAPTCHA_STORE.remove(captchaId);
            session.removeAttribute(CAPTCHA_SESSION_KEY + captchaId);
            log.warn("验证码已过期，captchaId: {}", captchaId);
            return false;
        }
        
        // 验证码不区分大小写
        boolean isValid = data.getCode().equalsIgnoreCase(captchaCode);
        
        // 验证后立即删除（一次性使用）
        CAPTCHA_STORE.remove(captchaId);
        session.removeAttribute(CAPTCHA_SESSION_KEY + captchaId);
        
        log.info("验证码验证{}，captchaId: {}", isValid ? "成功" : "失败", captchaId);
        
        return isValid;
    }

    /**
     * 清理过期验证码
     */
    private void cleanExpiredCaptcha() {
        long now = System.currentTimeMillis();
        CAPTCHA_STORE.entrySet().removeIf(entry -> 
            now - entry.getValue().getCreateTime() > CAPTCHA_EXPIRE_TIME
        );
    }

    /**
     * 验证码数据类
     */
    private static class CaptchaData {
        private final String code;
        private final long createTime;

        public CaptchaData(String code, long createTime) {
            this.code = code;
            this.createTime = createTime;
        }

        public String getCode() {
            return code;
        }

        public long getCreateTime() {
            return createTime;
        }
    }
}

